﻿using FastEmit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Dapper.Sharding
{
    public abstract partial class ITable<T> where T : class
    {
        protected abstract string SqlInsert();

        protected abstract string SqlInsert(List<string> fields);

        protected abstract string SqlInsertIgnore(List<string> fields);

        protected abstract string SqlInsertIdentity();

        protected abstract string SqlInsertIdentity(List<string> fields);

        protected abstract string SqlInsertIdentityIgnore(List<string> fields);

        protected abstract string SqlUpdate(List<string> fields = null);

        protected abstract string SqlUpdateIgnore(List<string> fields);

        protected abstract string SqlUpdateByWhere(string where, List<string> fields = null);

        protected abstract string SqlUpdateByWhereIgnore(string where, List<string> fields);

        protected abstract string SqlDeleteById();

        protected abstract string SqlDeleteByIds();

        protected abstract string SqlDeleteByWhere(string where);

        protected abstract string SqlDeleteAll();

        protected abstract string SqlExists();

        protected abstract string SqlExists(string where);

        protected abstract string SqlCount(string where = null);

        protected abstract string SqlMin(string field, string where = null);

        protected abstract string SqlMax(string field, string where = null);

        protected abstract string SqlSum(string field, string where = null);

        protected abstract string SqlAvg(string field, string where = null);

        protected abstract string SqlGetAll(string returnFields = null, string orderby = null);

        protected abstract string SqlGetById(string returnFields = null);

        protected abstract string SqlGetByIdForUpdate(string returnFields = null);

        protected abstract string SqlGetByIdForUpdateNoWait(string returnFields = null);

        protected abstract string SqlGetByIds(string returnFields = null);

        protected abstract string SqlGetByIdsForUpdate(string returnFields = null);

        protected abstract string SqlGetByIdsForUpdateNoWait(string returnFields = null);

        protected abstract string SqlGetByIdsWithField(string field, string returnFields = null);

        protected abstract string SqlGetByWhere(string where, string returnFields = null, string orderby = null, int limit = 0);

        protected abstract string SqlGetByWhereForUpdate(string where, string returnFields = null, string orderby = null, int limit = 0);

        protected abstract string SqlGetByWhereForUpdateNoWait(string where, string returnFields = null, string orderby = null, int limit = 0);

        protected abstract string SqlGetByWhereFirst(string where, string returnFields = null, string orderby = null);

        protected abstract string SqlGetByWhereFirstForUpdate(string where, string returnFields = null, string orderby = null);

        protected abstract string SqlGetByWhereFirstForUpdateNoWait(string where, string returnFields = null, string orderby = null);

        protected abstract string SqlGetBySkipTake(int skip, int take, string where = null, string returnFields = null, string orderby = null);

        protected abstract string SqlGetByAscFirstPage(int pageSize, string and = null, string returnFields = null);

        protected abstract string SqlGetByAscPrevPage(int pageSize, string and = null, string returnFields = null);

        protected abstract string SqlGetByAscCurrentPage(int pageSize, string and = null, string returnFields = null);

        protected abstract string SqlGetByAscNextPage(int pageSize, string and = null, string returnFields = null);

        protected abstract string SqlGetByAscLastPage(int pageSize, string and = null, string returnFields = null);

        protected abstract string SqlGetByDescFirstPage(int pageSize, string and = null, string returnFields = null);

        protected abstract string SqlGetByDescPrevPage(int pageSize, string and = null, string returnFields = null);

        protected abstract string SqlGetByDescCurrentPage(int pageSize, string and = null, string returnFields = null);

        protected abstract string SqlGetByDescNextPage(int pageSize, string and = null, string returnFields = null);

        protected abstract string SqlGetByDescLastPage(int pageSize, string and = null, string returnFields = null);

        public abstract void SeqUpdate(string name = null);

        public abstract Task SeqUpdateAsync(string name = null);
    }

    public abstract partial class ITable<T> where T : class
    {
        public ITable(string name, IDatabase database, SqlFieldEntity sqlField)
        {
            Name = name;
            DataBase = database;
            SqlField = sqlField;
        }

        #region prototype

        public string Name { get; }

        public IDatabase DataBase { get; }

        public DataBaseType DbType
        {
            get
            {
                return DataBase.DbType;
            }
        }

        public DataBaseVersion DbVersion
        {
            get
            {
                return DataBase.DbVersion;
            }
        }

        public SqlFieldEntity SqlField { get; }

        #endregion

        #region insert

        public void Insert(T model, DistributedTransaction tran = null, int? timeout = null)
        {
            var sql = SqlInsert();
            if (SqlField.IsIdentity)
            {
                var accessor = FastEmitFactory.GetTypeAccessor(typeof(T));
                if (SqlField.PrimaryKeyType == typeof(int))
                {
                    var id = DataBase.ExecuteScalar<int>(sql, model, tran, timeout);
                    accessor.SetValue(model, SqlField.PrimaryKey, id);
                }
                else
                {
                    var id = DataBase.ExecuteScalar<long>(sql, model, tran, timeout);
                    accessor.SetValue(model, SqlField.PrimaryKey, id);
                }
            }
            else
            {
                DataBase.Execute(sql, model, tran, timeout);
            }
        }

        public virtual void Insert(IEnumerable<T> list, DistributedTransaction tran = null, int? timeout = null)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in list)
                {
                    Insert(item, tn, timeout);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in list)
                {
                    Insert(item, tran, timeout);
                }
            }
        }

        public virtual void Insert(T model, List<string> fields, DistributedTransaction tran = null, int? timeout = null)
        {
            var sql = SqlInsert(fields);
            if (SqlField.IsIdentity)
            {
                var accessor = FastEmitFactory.GetTypeAccessor(typeof(T));
                if (SqlField.PrimaryKeyType == typeof(int))
                {
                    var id = DataBase.ExecuteScalar<int>(sql, model, tran, timeout);
                    accessor.SetValue(model, SqlField.PrimaryKey, id);
                }
                else
                {
                    var id = DataBase.ExecuteScalar<long>(sql, model, tran, timeout);
                    accessor.SetValue(model, SqlField.PrimaryKey, id);
                }
            }
            else
            {
                DataBase.Execute(sql, model, tran, timeout);
            }
        }

        public virtual void Insert(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    Insert(item, fields, tn, timeout);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    Insert(item, fields, tran, timeout);
                }
            }
        }

        public async Task InsertAsync(T model, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            var sql = SqlInsert();
            if (SqlField.IsIdentity)
            {
                var accessor = FastEmitFactory.GetTypeAccessor(typeof(T));
                if (SqlField.PrimaryKeyType == typeof(int))
                {
                    var id = await DataBase.ExecuteScalarAsync<int>(sql, model, tran, timeout, cancellationToken);
                    accessor.SetValue(model, SqlField.PrimaryKey, id);
                }
                else
                {
                    var id = await DataBase.ExecuteScalarAsync<long>(sql, model, tran, timeout, cancellationToken);
                    accessor.SetValue(model, SqlField.PrimaryKey, id);
                }
            }
            else
            {
                await DataBase.ExecuteAsync(sql, model, tran, timeout, cancellationToken);
            }
        }

        public virtual async Task InsertAsync(IEnumerable<T> list, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (tran == null)
            {

                using var tn = new DistributedTransaction();


                foreach (var item in list)
                {
                    await InsertAsync(item, tn, timeout, cancellationToken);
                }

                tn.Commit();


            }
            else
            {
                foreach (var item in list)
                {
                    await InsertAsync(item, tran, timeout, cancellationToken);
                }
            }
        }

        public virtual async Task InsertAsync(T model, List<string> fields, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            var sql = SqlInsert(fields);
            if (SqlField.IsIdentity)
            {
                var accessor = FastEmitFactory.GetTypeAccessor(typeof(T));
                if (SqlField.PrimaryKeyType == typeof(int))
                {
                    var id = await DataBase.ExecuteScalarAsync<int>(sql, model, tran, timeout, cancellationToken);
                    accessor.SetValue(model, SqlField.PrimaryKey, id);
                }
                else
                {
                    var id = await DataBase.ExecuteScalarAsync<long>(sql, model, tran, timeout, cancellationToken);
                    accessor.SetValue(model, SqlField.PrimaryKey, id);
                }
            }
            else
            {
                await DataBase.ExecuteAsync(sql, model, tran, timeout, cancellationToken);
            }
        }

        public virtual async Task InsertAsync(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (tran == null)
            {

                using var tn = new DistributedTransaction();

                foreach (var item in modelList)
                {
                    await InsertAsync(item, fields, tn, timeout, cancellationToken);
                }
                tn.Commit();

            }
            else
            {
                foreach (var item in modelList)
                {
                    await InsertAsync(item, fields, tran, timeout, cancellationToken);
                }
            }
        }

        public void InsertIdentity(T model, DistributedTransaction tran = null, int? timeout = null)
        {
            DataBase.Execute(SqlInsertIdentity(), model, tran, timeout);
        }

        public virtual void InsertIdentity(IEnumerable<T> list, DistributedTransaction tran = null, int? timeout = null)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in list)
                {
                    InsertIdentity(item, tn, timeout);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in list)
                {
                    InsertIdentity(item, tran, timeout);
                }
            }
        }

        public async Task InsertIdentityAsync(T model, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            await DataBase.ExecuteAsync(SqlInsertIdentity(), model, tran, timeout, cancellationToken);
        }

        public async Task InsertIdentityAsync(IEnumerable<T> list, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();

                foreach (var item in list)
                {
                    await InsertIdentityAsync(item, tn, timeout, cancellationToken);
                }
                tn.Commit();

            }
            else
            {
                foreach (var item in list)
                {
                    await InsertIdentityAsync(item, tran, timeout, cancellationToken);
                }
            }
        }

        public virtual void InsertIgnore(T model, List<string> fields, DistributedTransaction tran = null, int? timeout = null)
        {
            var sql = SqlInsertIgnore(fields);
            if (SqlField.IsIdentity)
            {
                var accessor = FastEmitFactory.GetTypeAccessor(typeof(T));
                if (SqlField.PrimaryKeyType == typeof(int))
                {
                    var id = DataBase.ExecuteScalar<int>(sql, model, tran, timeout);
                    accessor.SetValue(model, SqlField.PrimaryKey, id);
                }
                else
                {
                    var id = DataBase.ExecuteScalar<long>(sql, model, tran, timeout);
                    accessor.SetValue(model, SqlField.PrimaryKey, id);
                }
            }
            else
            {
                DataBase.Execute(sql, model, tran, timeout);
            }
        }

        public virtual void InsertIgnore(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    InsertIgnore(item, fields, tn, timeout);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    InsertIgnore(item, fields, tran, timeout);
                }
            }
        }

        public virtual async Task InsertIgnoreAsync(T model, List<string> fields, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            var sql = SqlInsertIgnore(fields);
            if (SqlField.IsIdentity)
            {
                var accessor = FastEmitFactory.GetTypeAccessor(typeof(T));
                if (SqlField.PrimaryKeyType == typeof(int))
                {
                    var id = await DataBase.ExecuteScalarAsync<int>(sql, model, tran, timeout, cancellationToken);
                    accessor.SetValue(model, SqlField.PrimaryKey, id);
                }
                else
                {
                    var id = await DataBase.ExecuteScalarAsync<long>(sql, model, tran, timeout, cancellationToken);
                    accessor.SetValue(model, SqlField.PrimaryKey, id);
                }
            }
            else
            {
                await DataBase.ExecuteAsync(sql, model, tran, timeout, cancellationToken);
            }
        }


        public virtual async Task InsertIgnoreAsync(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (tran == null)
            {

                using var tn = new DistributedTransaction();

                foreach (var item in modelList)
                {
                    await InsertIgnoreAsync(item, fields, tn, timeout, cancellationToken);
                }

                tn.Commit();

            }
            else
            {
                foreach (var item in modelList)
                {
                    await InsertIgnoreAsync(item, fields, tran, timeout, cancellationToken);
                }
            }
        }

        public virtual void InsertIfNoExists(T model, DistributedTransaction tran = null, int? timeout = null)
        {
            if (!Exists(model, tran, timeout))
            {
                Insert(model, tran, timeout);
            }
        }

        public virtual void InsertIfNoExists(IEnumerable<T> modelList, DistributedTransaction tran = null, int? timeout = null)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    InsertIfNoExists(item, tn, timeout);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    InsertIfNoExists(item, tran, timeout);
                }
            }
        }


        public virtual async Task InsertIfNoExistsAsync(T model, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (!await ExistsAsync(model, tran, timeout, cancellationToken))
            {
                await InsertAsync(model, tran, timeout, cancellationToken);
            }
        }


        public virtual async Task InsertIfNoExistsAsync(IEnumerable<T> modelList, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (tran == null)
            {

                using var tn = new DistributedTransaction();

                foreach (var item in modelList)
                {
                    await InsertIfNoExistsAsync(item, tn, timeout, cancellationToken);
                }
                tn.Commit();

            }
            else
            {
                foreach (var item in modelList)
                {
                    await InsertIfNoExistsAsync(item, tran, timeout, cancellationToken);
                }

            }
        }

        public virtual void InsertIfNoExists(T model, List<string> fields, DistributedTransaction tran = null, int? timeout = null)
        {
            if (!Exists(model, tran, timeout))
            {
                Insert(model, fields, tran, timeout);
            }
        }

        public virtual void InsertIfNoExists(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    InsertIfNoExists(item, fields, tn, timeout);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    InsertIfNoExists(item, fields, tran, timeout);
                }
            }
        }

        public virtual async Task InsertIfNoExistsAsync(T model, List<string> fields, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (!await ExistsAsync(model, tran, timeout, cancellationToken))
            {
                await InsertAsync(model, fields, tran, timeout, cancellationToken);
            }
        }

        public virtual async Task InsertIfNoExistsAsync(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    await InsertIfNoExistsAsync(item, fields, tn, timeout, cancellationToken);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    await InsertIfNoExistsAsync(item, fields, tran, timeout, cancellationToken);
                }

            }
        }

        public virtual void InsertIfNoExistsIgnore(T model, List<string> fields, DistributedTransaction tran = null, int? timeout = null)
        {
            if (!Exists(model, tran, timeout))
            {
                InsertIgnore(model, fields, tran, timeout);
            }
        }

        public virtual void InsertIfNoExistsIgnore(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    InsertIfNoExistsIgnore(item, fields, tn, timeout);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    InsertIfNoExistsIgnore(item, fields, tran, timeout);
                }
            }
        }


        public virtual async Task InsertIfNoExistsIgnoreAsync(T model, List<string> fields, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (!await ExistsAsync(model, tran, timeout, cancellationToken))
            {
                await InsertIgnoreAsync(model, fields, tran, timeout, cancellationToken);
            }
        }


        public virtual async Task InsertIfNoExistsIgnoreAsync(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    await InsertIfNoExistsIgnoreAsync(item, fields, tn, timeout, cancellationToken);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    await InsertIfNoExistsIgnoreAsync(item, fields, tran, timeout, cancellationToken);
                }

            }
        }

        public virtual void InsertIdentity(T model, List<string> fields, DistributedTransaction tran = null, int? timeout = null)
        {
            DataBase.Execute(SqlInsertIdentity(fields), model, tran, timeout);
        }

        public virtual void InsertIdentity(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    InsertIdentity(item, fields, tn, timeout);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    InsertIdentity(item, fields, tran, timeout);
                }
            }
        }

        public virtual async Task InsertIdentityAsync(T model, List<string> fields, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            await DataBase.ExecuteAsync(SqlInsertIdentity(fields), model, tran, timeout, cancellationToken);
        }


        public virtual async Task InsertIdentityAsync(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    await InsertIdentityAsync(item, fields, tn, timeout, cancellationToken);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    await InsertIdentityAsync(item, fields, tran, timeout, cancellationToken);
                }
            }
        }

        public virtual void InsertIdentityIgnore(T model, List<string> fields, DistributedTransaction tran = null, int? timeout = null)
        {
            DataBase.Execute(SqlInsertIdentityIgnore(fields), model, tran, timeout);
        }

        public virtual void InsertIdentityIgnore(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    InsertIdentityIgnore(item, fields, tn, timeout);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    InsertIdentityIgnore(item, fields, tran, timeout);
                }
            }
        }

        public virtual async Task InsertIdentityIgnoreAsync(T model, List<string> fields, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            await DataBase.ExecuteAsync(SqlInsertIdentityIgnore(fields), model, tran, timeout, cancellationToken);
        }

        public virtual async Task InsertIdentityIgnoreAsync(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    await InsertIdentityIgnoreAsync(item, fields, tn, timeout, cancellationToken);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    await InsertIdentityIgnoreAsync(item, fields, tran, timeout, cancellationToken);
                }
            }
        }

        public virtual void InsertIdentityIfNoExists(T model, DistributedTransaction tran = null, int? timeout = null)
        {
            if (!Exists(model, tran, timeout))
            {
                InsertIdentity(model, tran, timeout);
            }
        }

        public virtual void InsertIdentityIfNoExists(IEnumerable<T> modelList, DistributedTransaction tran = null, int? timeout = null)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    InsertIdentityIfNoExists(item, tn, timeout);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    InsertIdentityIfNoExists(item, tran, timeout);
                }
            }
        }

        public virtual async Task InsertIdentityIfNoExistsAsync(T model, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (!await ExistsAsync(model, tran, timeout, cancellationToken))
            {
                await InsertIdentityAsync(model, tran, timeout, cancellationToken);
            }
        }

        public virtual async Task InsertIdentityIfNoExistsAsync(IEnumerable<T> modelList, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    await InsertIdentityIfNoExistsAsync(item, tn, timeout, cancellationToken);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    await InsertIdentityIfNoExistsAsync(item, tran, timeout, cancellationToken);
                }
            }
        }

        public virtual void InsertIdentityIfNoExists(T model, List<string> fields, DistributedTransaction tran = null, int? timeout = null)
        {
            if (!Exists(model, tran, timeout))
            {
                InsertIdentity(model, fields, tran, timeout);
            }
        }

        public virtual void InsertIdentityIfNoExists(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    InsertIdentityIfNoExists(item, fields, tn, timeout);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    InsertIdentityIfNoExists(item, fields, tran, timeout);
                }
            }
        }

        public virtual async Task InsertIdentityIfNoExistsAsync(T model, List<string> fields, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (!await ExistsAsync(model, tran, timeout, cancellationToken))
            {
                await InsertIdentityAsync(model, fields, tran, timeout, cancellationToken);
            }
        }

        public virtual async Task InsertIdentityIfNoExistsAsync(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    await InsertIdentityIfNoExistsAsync(item, fields, tn, timeout, cancellationToken);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    await InsertIdentityIfNoExistsAsync(item, fields, tran, timeout, cancellationToken);
                }
            }
        }

        public virtual void InsertIdentityIfNoExistsIgnore(T model, List<string> fields, DistributedTransaction tran = null, int? timeout = null)
        {
            if (!Exists(model, tran, timeout))
            {
                InsertIdentityIgnore(model, fields, tran, timeout);
            }
        }

        public virtual void InsertIdentityIfNoExistsIgnore(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    InsertIdentityIfNoExistsIgnore(item, fields, tn, timeout);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    InsertIdentityIfNoExistsIgnore(item, fields, tran, timeout);
                }
            }
        }

        public virtual async Task InsertIdentityIfNoExistsIgnoreAsync(T model, List<string> fields, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (!await ExistsAsync(model, tran, timeout, cancellationToken))
            {
                await InsertIdentityIgnoreAsync(model, fields, tran, timeout, cancellationToken);
            }
        }

        public virtual async Task InsertIdentityIfNoExistsIgnoreAsync(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    await InsertIdentityIfNoExistsIgnoreAsync(item, fields, tn, timeout, cancellationToken);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    await InsertIdentityIfNoExistsIgnoreAsync(item, fields, tran, timeout, cancellationToken);
                }
            }
        }

        #endregion

        #region BulkInsert

        public virtual void BulkInsert(IEnumerable<T> modelList, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            DataBase.BulkInsert(Name, modelList, opt =>
            {
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }

            }, tran, batchSize);
        }

        public Task BulkInsertAsync(IEnumerable<T> modelList, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            return DataBase.BulkInsertAsync(Name, modelList, opt =>
            {
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }

            }, tran, batchSize);
        }

        public void BulkInsert(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            DataBase.BulkInsert(Name, modelList, opt =>
            {
                opt.IgnoreOnInsertNames = SqlField.AllFieldExceptKeyList.Except(fields).ToList();
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public Task BulkInsertAsync(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            return DataBase.BulkInsertAsync(Name, modelList, opt =>
            {
                opt.IgnoreOnInsertNames = SqlField.AllFieldExceptKeyList.Except(fields).ToList();
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public void BulkInsertIgnore(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            DataBase.BulkInsert(Name, modelList, opt =>
            {
                opt.IgnoreOnInsertNames = fields;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public Task BulkInsertIgnoreAsync(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            return DataBase.BulkInsertAsync(Name, modelList, opt =>
            {
                opt.IgnoreOnInsertNames = fields;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public void BulkInsertIfNoExists(IEnumerable<T> modelList, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            DataBase.BulkInsert(Name, modelList, opt =>
            {
                opt.InsertIfNotExists = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public Task BulkInsertIfNoExistsAsync(IEnumerable<T> modelList, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            return DataBase.BulkInsertAsync(Name, modelList, opt =>
            {
                opt.InsertIfNotExists = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public void BulkInsertIfNoExists(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            DataBase.BulkInsert(Name, modelList, opt =>
            {
                opt.IgnoreOnInsertNames = SqlField.AllFieldExceptKeyList.Except(fields).ToList();
                opt.InsertIfNotExists = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public Task BulkInsertIfNoExistsAsync(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            return DataBase.BulkInsertAsync(Name, modelList, opt =>
            {
                opt.IgnoreOnInsertNames = SqlField.AllFieldExceptKeyList.Except(fields).ToList();
                opt.InsertIfNotExists = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public void BulkInsertIfNoExistsIgnore(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            DataBase.BulkInsert(Name, modelList, opt =>
            {
                opt.IgnoreOnInsertNames = fields;
                opt.InsertIfNotExists = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public Task BulkInsertIfNoExistsIgnoreAsync(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            return DataBase.BulkInsertAsync(Name, modelList, opt =>
            {
                opt.IgnoreOnInsertNames = fields;
                opt.InsertIfNotExists = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public void BulkInsertIdentity(IEnumerable<T> modelList, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            DataBase.BulkInsert(Name, modelList, opt =>
            {
                opt.InsertKeepIdentity = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public Task BulkInsertIdentityAsync(IEnumerable<T> modelList, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            return DataBase.BulkInsertAsync(Name, modelList, opt =>
            {
                opt.InsertKeepIdentity = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public void BulkInsertIdentity(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            DataBase.BulkInsert(Name, modelList, opt =>
            {
                opt.IgnoreOnInsertNames = SqlField.AllFieldExceptKeyList.Except(fields).ToList();
                opt.InsertKeepIdentity = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public Task BulkInsertIdentityAsync(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            return DataBase.BulkInsertAsync(Name, modelList, opt =>
            {
                opt.IgnoreOnInsertNames = SqlField.AllFieldExceptKeyList.Except(fields).ToList();
                opt.InsertKeepIdentity = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public void BulkInsertIdentityIgnore(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            DataBase.BulkInsert(Name, modelList, opt =>
            {
                opt.IgnoreOnInsertNames = fields;
                opt.InsertKeepIdentity = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public Task BulkInsertIdentityIgnoreAsync(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            return DataBase.BulkInsertAsync(Name, modelList, opt =>
            {
                opt.IgnoreOnInsertNames = fields;
                opt.InsertKeepIdentity = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public void BulkInsertIdentityIfNoExists(IEnumerable<T> modelList, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            DataBase.BulkInsert(Name, modelList, opt =>
            {
                opt.InsertKeepIdentity = true;
                opt.InsertIfNotExists = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public Task BulkInsertIdentityIfNoExistsAsync(IEnumerable<T> modelList, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            return DataBase.BulkInsertAsync(Name, modelList, opt =>
            {
                opt.InsertKeepIdentity = true;
                opt.InsertIfNotExists = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public void BulkInsertIdentityIfNoExists(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            DataBase.BulkInsert(Name, modelList, opt =>
            {
                opt.IgnoreOnInsertNames = SqlField.AllFieldExceptKeyList.Except(fields).ToList();
                opt.InsertKeepIdentity = true;
                opt.InsertIfNotExists = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public Task BulkInsertIdentityIfNoExistsAsync(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            return DataBase.BulkInsertAsync(Name, modelList, opt =>
            {
                opt.IgnoreOnInsertNames = SqlField.AllFieldExceptKeyList.Except(fields).ToList();
                opt.InsertKeepIdentity = true;
                opt.InsertIfNotExists = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public void BulkInsertIdentityIfNoExistsIgnore(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            DataBase.BulkInsert(Name, modelList, opt =>
            {
                opt.IgnoreOnInsertNames = fields;
                opt.InsertKeepIdentity = true;
                opt.InsertIfNotExists = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public Task BulkInsertIdentityIfNoExistsIgnoreAsync(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            return DataBase.BulkInsertAsync(Name, modelList, opt =>
            {
                opt.IgnoreOnInsertNames = fields;
                opt.InsertKeepIdentity = true;
                opt.InsertIfNotExists = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        #endregion

        #region update

        public int Update(T model, List<string> fields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Execute(SqlUpdate(fields), model, tran, timeout);
        }

        public virtual void Update(IEnumerable<T> list, List<string> fields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in list)
                {
                    Update(item, fields, tn, timeout);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in list)
                {
                    Update(item, fields, tran, timeout);
                }
            }
        }

        public async Task<int> UpdateAsync(T model, List<string> fields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.ExecuteAsync(SqlUpdate(fields), model, tran, timeout, cancellationToken);
        }

        public async Task UpdateAsync(IEnumerable<T> list, List<string> fields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in list)
                {
                    await UpdateAsync(item, fields, tn, timeout, cancellationToken);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in list)
                {
                    await UpdateAsync(item, fields, tran, timeout, cancellationToken);
                }
            }
        }

        public int UpdateIgnore(T model, List<string> fields, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Execute(SqlUpdateIgnore(fields), model, tran, timeout);
        }

        public virtual void UpdateIgnore(IEnumerable<T> list, List<string> fields, DistributedTransaction tran = null, int? timeout = null)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in list)
                {
                    UpdateIgnore(item, fields, tn, timeout);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in list)
                {
                    UpdateIgnore(item, fields, tran, timeout);
                }
            }
        }

        public async Task<int> UpdateIgnoreAsync(T model, List<string> fields, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.ExecuteAsync(SqlUpdateIgnore(fields), model, tran, timeout, cancellationToken);
        }

        public async Task UpdateIgnoreAsync(IEnumerable<T> list, List<string> fields, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (tran == null)
            {

                using var tn = new DistributedTransaction();

                foreach (var item in list)
                {
                    await UpdateIgnoreAsync(item, fields, tn, timeout, cancellationToken);
                }
                tn.Commit();

            }
            else
            {
                foreach (var item in list)
                {
                    await UpdateIgnoreAsync(item, fields, tran, timeout, cancellationToken);
                }
            }
        }

        public int UpdateByWhere(object model, string where, List<string> fields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Execute(SqlUpdateByWhere(where, fields), model, tran, timeout);
        }

        public async Task<int> UpdateByWhereAsync(object model, string where, List<string> fields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.ExecuteAsync(SqlUpdateByWhere(where, fields), model, tran, timeout, cancellationToken);
        }

        public int UpdateByWhereIgnore(object model, string where, List<string> fields, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Execute(SqlUpdateByWhereIgnore(where, fields), model, tran, timeout);
        }

        public async Task<int> UpdateByWhereIgnoreAsync(object model, string where, List<string> fields, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.ExecuteAsync(SqlUpdateByWhereIgnore(where, fields), model, tran, timeout, cancellationToken);
        }

        #endregion

        #region BulkUpdate

        public void BulkUpdate(IEnumerable<T> modelList, List<string> fields = null, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            DataBase.BulkUpdate(Name, modelList, opt =>
            {
                if (fields != null)
                {
                    var ignoreFileds = SqlField.AllFieldExceptKeyList.Except(fields).ToList();
                    opt.IgnoreOnUpdateNames = ignoreFileds;
                    if (timeout != null)
                    {
                        opt.BatchTimeout = timeout.Value;
                    }
                }
            }, tran, batchSize);
        }

        public Task BulkUpdateAsync(IEnumerable<T> modelList, List<string> fields = null, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            return DataBase.BulkUpdateAsync(Name, modelList, opt =>
            {
                if (fields != null)
                {
                    var ignoreFileds = SqlField.AllFieldExceptKeyList.Except(fields).ToList();
                    opt.IgnoreOnUpdateNames = ignoreFileds;
                    if (timeout != null)
                    {
                        opt.BatchTimeout = timeout.Value;
                    }
                }
            }, tran, batchSize);
        }

        public void BulkUpdateIgnore(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            DataBase.BulkUpdate(Name, modelList, opt =>
            {
                opt.IgnoreOnUpdateNames = fields;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public Task BulkUpdateIgnoreAsync(IEnumerable<T> modelList, List<string> fields, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            return DataBase.BulkUpdateAsync(Name, modelList, opt =>
            {
                opt.IgnoreOnUpdateNames = fields;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        #endregion

        #region InsertOrUpdate

        private bool InitInsertOrUpdateModel(T model, IdType t)
        {
            var accessor = FastEmitFactory.GetTypeAccessor(typeof(T));
            var id = accessor.GetValue(model, SqlField.PrimaryKey);
            bool insert = true;
            if (id is int val)
            {
                if (val > 0)
                {
                    insert = false;
                }
            }
            else if (id is long val2)
            {
                if (val2 > 0)
                {
                    insert = false;
                }
                else
                {
                    if (!SqlField.IsIdentity)
                    {
                        if (t == IdType.SnowId)
                        {
                            accessor.SetValue(model, SqlField.PrimaryKey, ShardingFactory.NextSnowId());
                        }
                        else
                        {
                            accessor.SetValue(model, SqlField.PrimaryKey, ShardingFactory.NextLongId());
                        }
                    }
                }
            }
            else if (id is string val3)
            {
                if (!string.IsNullOrEmpty(val3))
                {
                    insert = false;
                }
                else
                {
                    if (t == IdType.ObjectId)
                    {
                        accessor.SetValue(model, SqlField.PrimaryKey, ShardingFactory.NextObjectId());
                    }
                    else if (t == IdType.SnowId)
                    {
                        accessor.SetValue(model, SqlField.PrimaryKey, ShardingFactory.NextSnowIdAsString());
                    }
                    else
                    {
                        accessor.SetValue(model, SqlField.PrimaryKey, ShardingFactory.NextLongIdAsString());
                    }

                }
            }
            else if (id is decimal val4)
            {
                if (val4 > 0)
                {
                    insert = false;
                }
            }
            return insert;
        }

        public void InsertOrUpdate(T model, List<string> updateFields = null, DistributedTransaction tran = null, int? timeout = null, IdType t = IdType.ObjectId)
        {
            var insert = InitInsertOrUpdateModel(model, t);
            if (insert)
            {
                Insert(model, tran, timeout);
            }
            else
            {
                Update(model, updateFields, tran, timeout);
            }

        }

        public async Task InsertOrUpdateAsync(T model, List<string> updateFields = null, DistributedTransaction tran = null, int? timeout = null, IdType t = IdType.ObjectId, CancellationToken cancellationToken = default)
        {
            var insert = InitInsertOrUpdateModel(model, t);
            if (insert)
            {
                await InsertAsync(model, tran, timeout, cancellationToken);
            }
            else
            {
                await UpdateAsync(model, updateFields, tran, timeout, cancellationToken);
            }

        }

        public void InsertOrUpdateIgnore(T model, List<string> ignoreFields, DistributedTransaction tran = null, int? timeout = null, IdType t = IdType.ObjectId)
        {
            var insert = InitInsertOrUpdateModel(model, t);
            if (insert)
            {
                Insert(model, tran, timeout);
            }
            else
            {
                UpdateIgnore(model, ignoreFields, tran, timeout);
            }

        }

        public async Task InsertOrUpdateIgnoreAsync(T model, List<string> ignoreFields, DistributedTransaction tran = null, int? timeout = null, IdType t = IdType.ObjectId, CancellationToken cancellationToken = default)
        {
            var insert = InitInsertOrUpdateModel(model, t);
            if (insert)
            {
                await InsertAsync(model, tran, timeout, cancellationToken);
            }
            else
            {
                await UpdateIgnoreAsync(model, ignoreFields, tran, timeout, cancellationToken);
            }

        }

        #endregion

        #region Merge

        public virtual void Merge(T model, List<string> fields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            var ok = Exists(model, tran, timeout);
            if (ok)
            {
                Update(model, fields, tran, timeout);
            }
            else
            {
                InsertIdentity(model, tran, timeout);
            }
        }

        public virtual void Merge(IEnumerable<T> modelList, List<string> fields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    Merge(item, fields, tn, timeout);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    Merge(item, fields, tran, timeout);
                }
            }
        }

        public virtual async Task MergeAsync(T model, List<string> fields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            var ok = await ExistsAsync(model, tran, timeout, cancellationToken);
            if (ok)
            {
                await UpdateAsync(model, fields, tran, timeout, cancellationToken);
            }
            else
            {
                await InsertIdentityAsync(model, tran, timeout, cancellationToken);
            }
        }

        public virtual async Task MergeAsync(IEnumerable<T> modelList, List<string> fields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    await MergeAsync(item, fields, tn, timeout, cancellationToken);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    await MergeAsync(item, fields, tran, timeout, cancellationToken);
                }
            }
        }

        public virtual void MergeIgnore(T model, List<string> fields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            var ok = Exists(model, tran, timeout);
            if (ok)
            {
                UpdateIgnore(model, fields, tran, timeout);
            }
            else
            {
                InsertIdentity(model, tran, timeout);
            }
        }

        public virtual void MergeIgnore(IEnumerable<T> modelList, List<string> fields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    MergeIgnore(item, fields, tn, timeout);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    MergeIgnore(item, fields, tran, timeout);
                }
            }
        }

        public virtual async Task MergeIgnoreAsync(T model, List<string> fields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            var ok = await ExistsAsync(model, tran, timeout, cancellationToken);
            if (ok)
            {
                await UpdateIgnoreAsync(model, fields, tran, timeout, cancellationToken);
            }
            else
            {
                await InsertIdentityAsync(model, tran, timeout, cancellationToken);
            }
        }

        public virtual async Task MergeIgnoreAsync(IEnumerable<T> modelList, List<string> fields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    await MergeIgnoreAsync(item, fields, tn, timeout, cancellationToken);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    await MergeIgnoreAsync(item, fields, tran, timeout, cancellationToken);
                }
            }
        }


        #endregion

        #region BulkMerge

        public void BulkMerge(IEnumerable<T> modelList, List<string> fields = null, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            DataBase.BulkMerge(Name, modelList, opt =>
            {
                if (fields != null)
                {
                    var ignoreFileds = SqlField.AllFieldExceptKeyList.Except(fields).ToList();
                    opt.IgnoreOnMergeUpdateNames = ignoreFileds;
                }
                opt.MergeKeepIdentity = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public Task BulkMergeAsync(IEnumerable<T> modelList, List<string> fields = null, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            return DataBase.BulkMergeAsync(Name, modelList, opt =>
            {
                if (fields != null)
                {
                    var ignoreFileds = SqlField.AllFieldExceptKeyList.Except(fields).ToList();
                    opt.IgnoreOnMergeUpdateNames = ignoreFileds;
                }
                opt.MergeKeepIdentity = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public void BulkMergeIgnore(IEnumerable<T> modelList, List<string> fields = null, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            DataBase.BulkMerge(Name, modelList, opt =>
            {
                if (fields != null)
                {
                    opt.IgnoreOnMergeUpdateNames = fields;
                }
                opt.MergeKeepIdentity = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        public Task BulkMergeIgnoreAsync(IEnumerable<T> modelList, List<string> fields = null, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            return DataBase.BulkMergeAsync(Name, modelList, opt =>
            {
                if (fields != null)
                {
                    opt.IgnoreOnMergeUpdateNames = fields;
                }
                opt.MergeKeepIdentity = true;
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        #endregion

        #region delete

        public int Delete(object id, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Execute(SqlDeleteById(), new { id }, tran, timeout);
        }

        public async Task<int> DeleteAsync(object id, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.ExecuteAsync(SqlDeleteById(), new { id }, tran, timeout, cancellationToken);
        }

        public int Delete(T model, DistributedTransaction tran = null, int? timeout = null)
        {
            var accessor = FastEmitFactory.GetTypeAccessor(typeof(T));
            var id = accessor.GetValue(model, SqlField.PrimaryKey);
            return Delete(id, tran, timeout);
        }

        public async Task<int> DeleteAsync(T model, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            var accessor = FastEmitFactory.GetTypeAccessor(typeof(T));
            var id = accessor.GetValue(model, SqlField.PrimaryKey);
            return await DeleteAsync(id, tran, timeout, cancellationToken);
        }

        public int DeleteByIds(object ids, DistributedTransaction tran = null, int? timeout = null)
        {
            if (CommonUtil.ObjectIsEmpty(ids))
                return 0;
            var dpar = new DynamicParameters();
            if (DbType == DataBaseType.Oracle)
            {
                dpar.Add(":ids", ids);
            }
            else if (DbType == DataBaseType.DuckDB)
            {
                dpar.Add("ids", ids);
            }
            else
            {
                dpar.Add("@ids", ids);
            }
            return DataBase.Execute(SqlDeleteByIds(), dpar, tran, timeout);
        }

        public async Task<int> DeleteByIdsAsync(object ids, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (CommonUtil.ObjectIsEmpty(ids))
                return 0;
            var dpar = new DynamicParameters();
            if (DbType == DataBaseType.Oracle)
            {
                dpar.Add(":ids", ids);
            }
            else if (DbType == DataBaseType.DuckDB)
            {
                dpar.Add("ids", ids);
            }
            else
            {
                dpar.Add("@ids", ids);
            }
            return await DataBase.ExecuteAsync(SqlDeleteByIds(), dpar, tran, timeout, cancellationToken);
        }

        public int DeleteByWhere(string where, object param = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Execute(SqlDeleteByWhere(where), param, tran, timeout);
        }

        public async Task<int> DeleteByWhereAsync(string where, object param = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.ExecuteAsync(SqlDeleteByWhere(where), param, tran, timeout, cancellationToken);
        }

        public int DeleteAll(DistributedTransaction tran = null, int? timeout = null)
        {
            var sql = SqlDeleteAll();
            if (sql == null)
            {
                return 1;
            }
            return DataBase.Execute(sql, null, tran, timeout);
        }

        public async Task<int> DeleteAllAsync(DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            var sql = SqlDeleteAll();
            if (sql == null)
            {
                return 0;
            }
            return await DataBase.ExecuteAsync(sql, null, tran, timeout, cancellationToken);
        }

        public virtual void Delete(IEnumerable<T> modelList, DistributedTransaction tran = null, int? timeout = null)
        {
            if (tran == null)
            {
                using var tn = new DistributedTransaction();
                foreach (var item in modelList)
                {
                    Delete(item, tn, timeout);
                }
                tn.Commit();
            }
            else
            {
                foreach (var item in modelList)
                {
                    Delete(item, tran, timeout);
                }
            }
        }

        public virtual async Task DeleteAsync(IEnumerable<T> modelList, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (tran == null)
            {

                using var tn = new DistributedTransaction();

                foreach (var item in modelList)
                {
                    await DeleteAsync(item, tn, timeout, cancellationToken);
                }

                tn.Commit();

            }
            else
            {
                foreach (var item in modelList)
                {
                    await DeleteAsync(item, tran, timeout, cancellationToken);
                }
            }
        }

        #endregion

        #region BulkDelete

        public void BulkDelete(IEnumerable<T> modelList, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            DataBase.BulkDelete(Name, modelList, opt =>
            {
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }

            }, tran, batchSize);
        }

        public Task BulkDeleteAsync(IEnumerable<T> modelList, DistributedTransaction tran = null, int? timeout = null, int? batchSize = null)
        {
            return DataBase.BulkDeleteAsync(Name, modelList, opt =>
            {
                if (timeout != null)
                {
                    opt.BatchTimeout = timeout.Value;
                }
            }, tran, batchSize);
        }

        #endregion

        #region aggregate

        public bool Exists(object id, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.ExecuteScalar<bool>(SqlExists(), new { id }, tran, timeout);
        }

        public async Task<bool> ExistsAsync(object id, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.ExecuteScalarAsync<bool>(SqlExists(), new { id }, tran, timeout, cancellationToken);
        }

        public bool ExistsWhere(string where, object param = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.ExecuteScalar<bool>(SqlExists(where), param, tran, timeout);
        }

        public async Task<bool> ExistsWhereAsync(string where, object param = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.ExecuteScalarAsync<bool>(SqlExists(where), param, tran, timeout, cancellationToken);
        }

        public bool Exists(T model, DistributedTransaction tran = null, int? timeout = null)
        {
            var accessor = FastEmitFactory.GetTypeAccessor(typeof(T));
            var id = accessor.GetValue(model, SqlField.PrimaryKey);
            return Exists(id, tran, timeout);
        }

        public async Task<bool> ExistsAsync(T model, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            var accessor = FastEmitFactory.GetTypeAccessor(typeof(T));
            var id = accessor.GetValue(model, SqlField.PrimaryKey);
            return await ExistsAsync(id, tran, timeout, cancellationToken);
        }

        public long Count(string where = null, object param = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.ExecuteScalar<long>(SqlCount(where), param, tran, timeout);
        }

        public async Task<long> CountAsync(string where = null, object param = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.ExecuteScalarAsync<long>(SqlCount(where), param, tran, timeout, cancellationToken);
        }

        public TValue Min<TValue>(string field, string where = null, object param = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.ExecuteScalar<TValue>(SqlMin(field, where), param, tran, timeout);
        }

        public async Task<TValue> MinAsync<TValue>(string field, string where = null, object param = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.ExecuteScalarAsync<TValue>(SqlMin(field, where), param, tran, timeout, cancellationToken);
        }

        public TValue Max<TValue>(string field, string where = null, object param = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.ExecuteScalar<TValue>(SqlMax(field, where), param, tran, timeout);
        }

        public async Task<TValue> MaxAsync<TValue>(string field, string where = null, object param = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.ExecuteScalarAsync<TValue>(SqlMax(field, where), param, tran, timeout, cancellationToken);
        }

        public TValue Sum<TValue>(string field, string where = null, object param = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.ExecuteScalar<TValue>(SqlSum(field, where), param, tran, timeout);
        }

        public async Task<TValue> SumAsync<TValue>(string field, string where = null, object param = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.ExecuteScalarAsync<TValue>(SqlSum(field, where), param, tran, timeout, cancellationToken);
        }

        public decimal Avg(string field, string where = null, object param = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.ExecuteScalar<decimal>(SqlAvg(field, where), param, tran, timeout);
        }

        public async Task<decimal> AvgAsync(string field, string where = null, object param = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.ExecuteScalarAsync<decimal>(SqlAvg(field, where), param, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetAll

        public List<T> GetAll(string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query<T>(SqlGetAll(returnFields, orderby), null, tran, timeout);
        }

        public async Task<List<T>> GetAllAsync(string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync<T>(SqlGetAll(returnFields, orderby), null, tran, timeout, cancellationToken);
        }

        public List<dynamic> GetAllDynamic(string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query(SqlGetAll(returnFields, orderby), null, tran, timeout);
        }

        public async Task<List<dynamic>> GetAllDynamicAsync(string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync(SqlGetAll(returnFields, orderby), null, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetById

        public T GetById(object id, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.QueryFirstOrDefault<T>(SqlGetById(returnFields), new { id }, tran, timeout);
        }

        public async Task<T> GetByIdAsync(object id, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryFirstOrDefaultAsync<T>(SqlGetById(returnFields), new { id }, tran, timeout, cancellationToken);
        }

        public dynamic GetByIdDynamic(object id, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.QueryFirstOrDefault(SqlGetById(returnFields), new { id }, tran, timeout);
        }

        public async Task<dynamic> GetByIdDynamicAsync(object id, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryFirstOrDefaultAsync(SqlGetById(returnFields), new { id }, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetByIdForUpdate

        public T GetByIdForUpdate(object id, DistributedTransaction tran, string returnFields = null, int? timeout = null)
        {
            return DataBase.QueryFirstOrDefault<T>(SqlGetByIdForUpdate(returnFields), new { id }, tran, timeout);
        }

        public async Task<T> GetByIdForUpdateAsync(object id, DistributedTransaction tran, string returnFields = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryFirstOrDefaultAsync<T>(SqlGetByIdForUpdate(returnFields), new { id }, tran, timeout, cancellationToken);
        }

        public dynamic GetByIdForUpdateDynamic(object id, DistributedTransaction tran, string returnFields = null, int? timeout = null)
        {
            return DataBase.QueryFirstOrDefault(SqlGetByIdForUpdate(returnFields), new { id }, tran, timeout);
        }

        public async Task<dynamic> GetByIdForUpdateDynamicAsync(object id, DistributedTransaction tran, string returnFields = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryFirstOrDefaultAsync(SqlGetByIdForUpdate(returnFields), new { id }, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetByIdForUpdateNoWait

        public T GetByIdForUpdateNoWait(object id, DistributedTransaction tran, string returnFields = null, int? timeout = null)
        {
            return DataBase.QueryFirstOrDefault<T>(SqlGetByIdForUpdateNoWait(returnFields), new { id }, tran, timeout);
        }

        public async Task<T> GetByIdForUpdateNoWaitAsync(object id, DistributedTransaction tran, string returnFields = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryFirstOrDefaultAsync<T>(SqlGetByIdForUpdateNoWait(returnFields), new { id }, tran, timeout, cancellationToken);
        }

        public dynamic GetByIdForUpdateNoWaitDynamic(object id, DistributedTransaction tran, string returnFields = null, int? timeout = null)
        {
            return DataBase.QueryFirstOrDefault(SqlGetByIdForUpdateNoWait(returnFields), new { id }, tran, timeout);
        }

        public async Task<dynamic> GetByIdForUpdateNoWaitDynamicAsync(object id, DistributedTransaction tran, string returnFields = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryFirstOrDefaultAsync(SqlGetByIdForUpdateNoWait(returnFields), new { id }, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetByIds

        public List<T> GetByIds(object ids, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            if (CommonUtil.ObjectIsEmpty(ids))
                return new List<T>();
            var dpar = new DynamicParameters();
            if (DbType == DataBaseType.Oracle)
            {
                dpar.Add(":ids", ids);
            }
            else if (DbType == DataBaseType.DuckDB)
            {
                dpar.Add("ids", ids);
            }
            else
            {
                dpar.Add("@ids", ids);
            }
            return DataBase.Query<T>(SqlGetByIds(returnFields), dpar, tran, timeout);
        }

        public async Task<List<T>> GetByIdsAsync(object ids, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (CommonUtil.ObjectIsEmpty(ids))
                return new List<T>();
            var dpar = new DynamicParameters();
            if (DbType == DataBaseType.Oracle)
            {
                dpar.Add(":ids", ids);
            }
            else if (DbType == DataBaseType.DuckDB)
            {
                dpar.Add("ids", ids);
            }
            else
            {
                dpar.Add("@ids", ids);
            }
            return await DataBase.QueryAsync<T>(SqlGetByIds(returnFields), dpar, tran, timeout, cancellationToken);
        }

        public List<dynamic> GetByIdsDynamic(object ids, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            if (CommonUtil.ObjectIsEmpty(ids))
                return new List<dynamic>();

            var dpar = new DynamicParameters();
            if (DbType == DataBaseType.Oracle)
            {
                dpar.Add(":ids", ids);
            }
            else if (DbType == DataBaseType.DuckDB)
            {
                dpar.Add("ids", ids);
            }
            else
            {
                dpar.Add("@ids", ids);
            }
            return DataBase.Query(SqlGetByIds(returnFields), dpar, tran, timeout);
        }

        public async Task<List<dynamic>> GetByIdsDynamicAsync(object ids, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (CommonUtil.ObjectIsEmpty(ids))
                return new List<dynamic>();

            var dpar = new DynamicParameters();
            if (DbType == DataBaseType.Oracle)
            {
                dpar.Add(":ids", ids);
            }
            else if (DbType == DataBaseType.DuckDB)
            {
                dpar.Add("ids", ids);
            }
            else
            {
                dpar.Add("@ids", ids);
            }
            return await DataBase.QueryAsync(SqlGetByIds(returnFields), dpar, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetByIdsForUpdate

        public List<T> GetByIdsForUpdate(object ids, DistributedTransaction tran, string returnFields = null, int? timeout = null)
        {
            if (CommonUtil.ObjectIsEmpty(ids))
                return new List<T>();

            var dpar = new DynamicParameters();
            if (DbType == DataBaseType.Oracle)
            {
                dpar.Add(":ids", ids);
            }
            else if (DbType == DataBaseType.DuckDB)
            {
                dpar.Add("ids", ids);
            }
            else
            {
                dpar.Add("@ids", ids);
            }
            return DataBase.Query<T>(SqlGetByIdsForUpdate(returnFields), dpar, tran, timeout);
        }

        public async Task<List<T>> GetByIdsForUpdateAsync(object ids, DistributedTransaction tran, string returnFields = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (CommonUtil.ObjectIsEmpty(ids))
                return new List<T>();

            var dpar = new DynamicParameters();
            if (DbType == DataBaseType.Oracle)
            {
                dpar.Add(":ids", ids);
            }
            else if (DbType == DataBaseType.DuckDB)
            {
                dpar.Add("ids", ids);
            }
            else
            {
                dpar.Add("@ids", ids);
            }
            return await DataBase.QueryAsync<T>(SqlGetByIdsForUpdate(returnFields), dpar, tran, timeout, cancellationToken);
        }

        public List<dynamic> GetByIdsForUpdateDynamic(object ids, DistributedTransaction tran, string returnFields = null, int? timeout = null)
        {
            if (CommonUtil.ObjectIsEmpty(ids))
                return new List<dynamic>();

            var dpar = new DynamicParameters();
            if (DbType == DataBaseType.Oracle)
            {
                dpar.Add(":ids", ids);
            }
            else if (DbType == DataBaseType.DuckDB)
            {
                dpar.Add("ids", ids);
            }
            else
            {
                dpar.Add("@ids", ids);
            }
            return DataBase.Query(SqlGetByIdsForUpdate(returnFields), dpar, tran, timeout);
        }

        public async Task<List<dynamic>> GetByIdsForUpdateDynamicAsync(object ids, DistributedTransaction tran, string returnFields = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (CommonUtil.ObjectIsEmpty(ids))
                return new List<dynamic>();
            var dpar = new DynamicParameters();
            if (DbType == DataBaseType.Oracle)
            {
                dpar.Add(":ids", ids);
            }
            else if (DbType == DataBaseType.DuckDB)
            {
                dpar.Add("ids", ids);
            }
            else
            {
                dpar.Add("@ids", ids);
            }
            return await DataBase.QueryAsync(SqlGetByIdsForUpdate(returnFields), dpar, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetByIdsForUpdateNoWait

        public List<T> GetByIdsForUpdateNoWait(object ids, DistributedTransaction tran, string returnFields = null, int? timeout = null)
        {
            if (CommonUtil.ObjectIsEmpty(ids))
                return new List<T>();

            var dpar = new DynamicParameters();
            if (DbType == DataBaseType.Oracle)
            {
                dpar.Add(":ids", ids);
            }
            else if (DbType == DataBaseType.DuckDB)
            {
                dpar.Add("ids", ids);
            }
            else
            {
                dpar.Add("@ids", ids);
            }
            return DataBase.Query<T>(SqlGetByIdsForUpdateNoWait(returnFields), dpar, tran, timeout);
        }

        public async Task<List<T>> GetByIdsForUpdateNoWaitAsync(object ids, DistributedTransaction tran, string returnFields = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (CommonUtil.ObjectIsEmpty(ids))
                return new List<T>();

            var dpar = new DynamicParameters();
            if (DbType == DataBaseType.Oracle)
            {
                dpar.Add(":ids", ids);
            }
            else if (DbType == DataBaseType.DuckDB)
            {
                dpar.Add("ids", ids);
            }
            else
            {
                dpar.Add("@ids", ids);
            }
            return await DataBase.QueryAsync<T>(SqlGetByIdsForUpdateNoWait(returnFields), dpar, tran, timeout, cancellationToken);
        }

        public List<dynamic> GetByIdsForUpdateNoWaitDynamic(object ids, DistributedTransaction tran, string returnFields = null, int? timeout = null)
        {
            if (CommonUtil.ObjectIsEmpty(ids))
                return new List<dynamic>();

            var dpar = new DynamicParameters();
            if (DbType == DataBaseType.Oracle)
            {
                dpar.Add(":ids", ids);
            }
            else if (DbType == DataBaseType.DuckDB)
            {
                dpar.Add("ids", ids);
            }
            else
            {
                dpar.Add("@ids", ids);
            }
            return DataBase.Query(SqlGetByIdsForUpdateNoWait(returnFields), dpar, tran, timeout);
        }

        public async Task<List<dynamic>> GetByIdsForUpdateNoWaitDynamicAsync(object ids, DistributedTransaction tran, string returnFields = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (CommonUtil.ObjectIsEmpty(ids))
                return new List<dynamic>();

            var dpar = new DynamicParameters();
            if (DbType == DataBaseType.Oracle)
            {
                dpar.Add(":ids", ids);
            }
            else if (DbType == DataBaseType.DuckDB)
            {
                dpar.Add("ids", ids);
            }
            else
            {
                dpar.Add("@ids", ids);
            }
            return await DataBase.QueryAsync(SqlGetByIdsForUpdateNoWait(returnFields), dpar, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetByIdsWithField

        public List<T> GetByIdsWithField(object ids, string field, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            if (CommonUtil.ObjectIsEmpty(ids))
                return new List<T>();

            var dpar = new DynamicParameters();
            if (DbType == DataBaseType.Oracle)
            {
                dpar.Add(":ids", ids);
            }
            else if (DbType == DataBaseType.DuckDB)
            {
                dpar.Add("ids", ids);
            }
            else
            {
                dpar.Add("@ids", ids);
            }
            return DataBase.Query<T>(SqlGetByIdsWithField(field, returnFields), dpar, tran, timeout);
        }

        public async Task<List<T>> GetByIdsWithFieldAsync(object ids, string field, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (CommonUtil.ObjectIsEmpty(ids))
                return new List<T>();

            var dpar = new DynamicParameters();
            if (DbType == DataBaseType.Oracle)
            {
                dpar.Add(":ids", ids);
            }
            else if (DbType == DataBaseType.DuckDB)
            {
                dpar.Add("ids", ids);
            }
            else
            {
                dpar.Add("@ids", ids);
            }
            return await DataBase.QueryAsync<T>(SqlGetByIdsWithField(field, returnFields), dpar, tran, timeout, cancellationToken);
        }

        public List<dynamic> GetByIdsWithFieldDynamic(object ids, string field, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            if (CommonUtil.ObjectIsEmpty(ids))
                return new List<dynamic>();

            var dpar = new DynamicParameters();
            if (DbType == DataBaseType.Oracle)
            {
                dpar.Add(":ids", ids);
            }
            else if (DbType == DataBaseType.DuckDB)
            {
                dpar.Add("ids", ids);
            }
            else
            {
                dpar.Add("@ids", ids);
            }
            return DataBase.Query(SqlGetByIdsWithField(field, returnFields), dpar, tran, timeout);
        }

        public async Task<List<dynamic>> GetByIdsWithFieldDynamicAsync(object ids, string field, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (CommonUtil.ObjectIsEmpty(ids))
                return new List<dynamic>();

            var dpar = new DynamicParameters();
            if (DbType == DataBaseType.Oracle)
            {
                dpar.Add(":ids", ids);
            }
            else if (DbType == DataBaseType.DuckDB)
            {
                dpar.Add("ids", ids);
            }
            else
            {
                dpar.Add("@ids", ids);
            }
            return await DataBase.QueryAsync(SqlGetByIdsWithField(field, returnFields), dpar, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetByWhere

        public List<T> GetByWhere(string where, object param = null, string returnFields = null, string orderby = null, int limit = 0, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query<T>(SqlGetByWhere(where, returnFields, orderby, limit), param, tran, timeout);
        }

        public async Task<List<T>> GetByWhereAsync(string where, object param = null, string returnFields = null, string orderby = null, int limit = 0, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync<T>(SqlGetByWhere(where, returnFields, orderby, limit), param, tran, timeout, cancellationToken);
        }

        public List<dynamic> GetByWhereDynamic(string where, object param = null, string returnFields = null, string orderby = null, int limit = 0, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query(SqlGetByWhere(where, returnFields, orderby, limit), param, tran, timeout);
        }

        public async Task<List<dynamic>> GetByWhereDynamicAsync(string where, object param = null, string returnFields = null, string orderby = null, int limit = 0, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync(SqlGetByWhere(where, returnFields, orderby, limit), param, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetByWhereForUpdate

        public List<T> GetByWhereForUpdate(string where, object param = null, string returnFields = null, string orderby = null, int limit = 0, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query<T>(SqlGetByWhereForUpdate(where, returnFields, orderby, limit), param, tran, timeout);
        }

        public async Task<List<T>> GetByWhereForUpdateAsync(string where, object param = null, string returnFields = null, string orderby = null, int limit = 0, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync<T>(SqlGetByWhereForUpdate(where, returnFields, orderby, limit), param, tran, timeout, cancellationToken);
        }

        public List<dynamic> GetByWhereForUpdateDynamic(string where, object param = null, string returnFields = null, string orderby = null, int limit = 0, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query(SqlGetByWhereForUpdate(where, returnFields, orderby, limit), param, tran, timeout);
        }

        public async Task<List<dynamic>> GetByWhereForUpdateDynamicAsync(string where, object param = null, string returnFields = null, string orderby = null, int limit = 0, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync(SqlGetByWhereForUpdate(where, returnFields, orderby, limit), param, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetByWhereForUpdateNoWait

        public List<T> GetByWhereForUpdateNoWait(string where, object param = null, string returnFields = null, string orderby = null, int limit = 0, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query<T>(SqlGetByWhereForUpdateNoWait(where, returnFields, orderby, limit), param, tran, timeout);
        }

        public async Task<List<T>> GetByWhereForUpdateNoWaitAsync(string where, object param = null, string returnFields = null, string orderby = null, int limit = 0, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync<T>(SqlGetByWhereForUpdateNoWait(where, returnFields, orderby, limit), param, tran, timeout, cancellationToken);
        }

        public List<dynamic> GetByWhereForUpdateNoWaitDynamic(string where, object param = null, string returnFields = null, string orderby = null, int limit = 0, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query(SqlGetByWhereForUpdateNoWait(where, returnFields, orderby, limit), param, tran, timeout);
        }

        public async Task<List<dynamic>> GetByWhereForUpdateNoWaitDynamicAsync(string where, object param = null, string returnFields = null, string orderby = null, int limit = 0, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync(SqlGetByWhereForUpdateNoWait(where, returnFields, orderby, limit), param, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetByWhereFirst

        public T GetByWhereFirst(string where, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.QueryFirstOrDefault<T>(SqlGetByWhereFirst(where, returnFields, orderby), param, tran, timeout);
        }

        public async Task<T> GetByWhereFirstAsync(string where, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryFirstOrDefaultAsync<T>(SqlGetByWhereFirst(where, returnFields, orderby), param, tran, timeout, cancellationToken);
        }

        public dynamic GetByWhereFirstDynamic(string where, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.QueryFirstOrDefault(SqlGetByWhereFirst(where, returnFields, orderby), param, tran, timeout);
        }

        public async Task<dynamic> GetByWhereFirstDynamicAsync(string where, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryFirstOrDefaultAsync(SqlGetByWhereFirst(where, returnFields, orderby), param, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetByWhereFirstForUpdate

        public T GetByWhereFirstForUpdate(string where, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.QueryFirstOrDefault<T>(SqlGetByWhereFirstForUpdate(where, returnFields, orderby), param, tran, timeout);
        }

        public async Task<T> GetByWhereFirstForUpdateAsync(string where, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryFirstOrDefaultAsync<T>(SqlGetByWhereFirstForUpdate(where, returnFields, orderby), param, tran, timeout, cancellationToken);
        }

        public dynamic GetByWhereFirstForUpdateDynamic(string where, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.QueryFirstOrDefault(SqlGetByWhereFirstForUpdate(where, returnFields, orderby), param, tran, timeout);
        }

        public async Task<dynamic> GetByWhereFirstForUpdateDynamicAsync(string where, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryFirstOrDefaultAsync(SqlGetByWhereFirstForUpdate(where, returnFields, orderby), param, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetByWhereFirstForUpdateNoWait

        public T GetByWhereFirstForUpdateNoWait(string where, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.QueryFirstOrDefault<T>(SqlGetByWhereFirstForUpdateNoWait(where, returnFields, orderby), param, tran, timeout);
        }

        public async Task<T> GetByWhereFirstForUpdateNoWaitAsync(string where, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryFirstOrDefaultAsync<T>(SqlGetByWhereFirstForUpdateNoWait(where, returnFields, orderby), param, tran, timeout, cancellationToken);
        }

        public dynamic GetByWhereFirstForUpdateNoWaitDynamic(string where, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.QueryFirstOrDefault(SqlGetByWhereFirstForUpdateNoWait(where, returnFields, orderby), param, tran, timeout);
        }

        public async Task<dynamic> GetByWhereFirstForUpdateNoWaitDynamicAsync(string where, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryFirstOrDefaultAsync(SqlGetByWhereFirstForUpdateNoWait(where, returnFields, orderby), param, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetBySkipTake

        public List<T> GetBySkipTake(int skip, int take, string where = null, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query<T>(SqlGetBySkipTake(skip, take, where, returnFields, orderby), param, tran, timeout);
        }

        public async Task<List<T>> GetBySkipTakeAsync(int skip, int take, string where = null, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync<T>(SqlGetBySkipTake(skip, take, where, returnFields, orderby), param, tran, timeout, cancellationToken);
        }

        public List<dynamic> GetBySkipTakeDynamic(int skip, int take, string where = null, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query(SqlGetBySkipTake(skip, take, where, returnFields, orderby), param, tran, timeout);
        }

        public async Task<List<dynamic>> GetBySkipTakeDynamicAsync(int skip, int take, string where = null, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync(SqlGetBySkipTake(skip, take, where, returnFields, orderby), param, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetByAscFirstPage

        public List<T> GetByAscFirstPage(int pageSize, object param = null, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query<T>(SqlGetByAscFirstPage(pageSize, and, returnFields), param, tran, timeout);
        }

        public async Task<List<T>> GetByAscFirstPageAsync(int pageSize, object param = null, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync<T>(SqlGetByAscFirstPage(pageSize, and, returnFields), param, tran, timeout, cancellationToken);
        }

        public List<dynamic> GetByAscFirstPageDynamic(int pageSize, object param = null, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query(SqlGetByAscFirstPage(pageSize, and, returnFields), param, tran, timeout);
        }

        public async Task<List<dynamic>> GetByAscFirstPageDynamicAsync(int pageSize, object param = null, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync(SqlGetByAscFirstPage(pageSize, and, returnFields), param, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetByAscPrevPage

        public List<T> GetByAscPrevPage(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query<T>(SqlGetByAscPrevPage(pageSize, and, returnFields), param, tran, timeout);
        }

        public async Task<List<T>> GetByAscPrevPageAsync(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync<T>(SqlGetByAscPrevPage(pageSize, and, returnFields), param, tran, timeout, cancellationToken);
        }

        public List<dynamic> GetByAscPrevPageDynamic(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query(SqlGetByAscPrevPage(pageSize, and, returnFields), param, tran, timeout);
        }

        public async Task<List<dynamic>> GetByAscPrevPageDynamicAsync(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync(SqlGetByAscPrevPage(pageSize, and, returnFields), param, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetByAscCurrentPage

        public List<T> GetByAscCurrentPage(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query<T>(SqlGetByAscCurrentPage(pageSize, and, returnFields), param, tran, timeout);
        }

        public async Task<List<T>> GetByAscCurrentPageAsync(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync<T>(SqlGetByAscCurrentPage(pageSize, and, returnFields), param, tran, timeout, cancellationToken);
        }

        public List<dynamic> GetByAscCurrentPageDynamic(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query(SqlGetByAscCurrentPage(pageSize, and, returnFields), param, tran, timeout);
        }

        public async Task<List<dynamic>> GetByAscCurrentPageDynamicAsync(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync(SqlGetByAscCurrentPage(pageSize, and, returnFields), param, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetByAscNextPage

        public List<T> GetByAscNextPage(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query<T>(SqlGetByAscNextPage(pageSize, and, returnFields), param, tran, timeout);
        }

        public async Task<List<T>> GetByAscNextPageAsync(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync<T>(SqlGetByAscNextPage(pageSize, and, returnFields), param, tran, timeout, cancellationToken);
        }

        public List<dynamic> GetByAscNextPageDynamic(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query(SqlGetByAscNextPage(pageSize, and, returnFields), param, tran, timeout);
        }

        public async Task<List<dynamic>> GetByAscNextPageDynamicAsync(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync(SqlGetByAscNextPage(pageSize, and, returnFields), param, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetByAscLastPage


        public List<T> GetByAscLastPage(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query<T>(SqlGetByAscLastPage(pageSize, and, returnFields), param, tran, timeout);
        }

        public async Task<List<T>> GetByAscLastPageAsync(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync<T>(SqlGetByAscLastPage(pageSize, and, returnFields), param, tran, timeout, cancellationToken);
        }

        public List<dynamic> GetByAscLastPageDynamic(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query(SqlGetByAscLastPage(pageSize, and, returnFields), param, tran, timeout);
        }

        public async Task<List<dynamic>> GetByAscLastPageDynamicAsync(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync(SqlGetByAscLastPage(pageSize, and, returnFields), param, tran, timeout, cancellationToken);
        }


        #endregion

        #region GetByDescFirstPage

        public List<T> GetByDescFirstPage(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query<T>(SqlGetByDescFirstPage(pageSize, and, returnFields), param, tran, timeout);
        }

        public async Task<List<T>> GetByDescFirstPageAsync(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync<T>(SqlGetByDescFirstPage(pageSize, and, returnFields), param, tran, timeout, cancellationToken);
        }

        public List<dynamic> GetByDescFirstPageDynamic(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query(SqlGetByDescFirstPage(pageSize, and, returnFields), param, tran, timeout);
        }

        public async Task<List<dynamic>> GetByDescFirstPageDynamicAsync(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync(SqlGetByDescFirstPage(pageSize, and, returnFields), param, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetByDescPrevPage

        public List<T> GetByDescPrevPage(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query<T>(SqlGetByDescPrevPage(pageSize, and, returnFields), param, tran, timeout);
        }

        public async Task<List<T>> GetByDescPrevPageAsync(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync<T>(SqlGetByDescPrevPage(pageSize, and, returnFields), param, tran, timeout, cancellationToken);
        }

        public List<dynamic> GetByDescPrevPageDynamic(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query(SqlGetByDescPrevPage(pageSize, and, returnFields), param, tran, timeout);
        }

        public async Task<List<dynamic>> GetByDescPrevPageDynamicAsync(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync(SqlGetByDescPrevPage(pageSize, and, returnFields), param, tran, timeout, cancellationToken);
        }


        #endregion

        #region GetByDescCurrentPage

        public List<T> GetByDescCurrentPage(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query<T>(SqlGetByDescCurrentPage(pageSize, and, returnFields), param, tran, timeout);
        }

        public async Task<List<T>> GetByDescCurrentPageAsync(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync<T>(SqlGetByDescCurrentPage(pageSize, and, returnFields), param, tran, timeout, cancellationToken);
        }

        public List<dynamic> GetByDescCurrentPageDynamic(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query(SqlGetByDescCurrentPage(pageSize, and, returnFields), param, tran, timeout);
        }

        public async Task<List<dynamic>> GetByDescCurrentPageDynamicAsync(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync(SqlGetByDescCurrentPage(pageSize, and, returnFields), param, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetByDescNextPage

        public List<T> GetByDescNextPage(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query<T>(SqlGetByDescNextPage(pageSize, and, returnFields), param, tran, timeout);
        }

        public async Task<List<T>> GetByDescNextPageAsync(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync<T>(SqlGetByDescNextPage(pageSize, and, returnFields), param, tran, timeout, cancellationToken);
        }

        public List<dynamic> GetByDescNextPageDynamic(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query(SqlGetByDescNextPage(pageSize, and, returnFields), param, tran, timeout);
        }

        public async Task<List<dynamic>> GetByDescNextPageDynamicAsync(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync(SqlGetByDescNextPage(pageSize, and, returnFields), param, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetByDescLastPage

        public List<T> GetByDescLastPage(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query<T>(SqlGetByDescLastPage(pageSize, and, returnFields), param, tran, timeout);
        }

        public async Task<List<T>> GetByDescLastPageAsync(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync<T>(SqlGetByDescLastPage(pageSize, and, returnFields), param, tran, timeout, cancellationToken);
        }

        public List<dynamic> GetByDescLastPageDynamic(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return DataBase.Query(SqlGetByDescLastPage(pageSize, and, returnFields), param, tran, timeout);
        }

        public async Task<List<dynamic>> GetByDescLastPageDynamicAsync(int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            return await DataBase.QueryAsync(SqlGetByDescLastPage(pageSize, and, returnFields), param, tran, timeout, cancellationToken);
        }

        #endregion

        /*******以下方法仅调用上面方法********/

        #region GetByPage

        public List<T> GetByPage(int page, int pageSize, string where = null, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null)
        {
            int skip = 0;
            if (page > 1)
            {
                skip = (page - 1) * pageSize;
            }
            return GetBySkipTake(skip, pageSize, where, param, returnFields, orderby, tran, timeout);
        }

        public async Task<List<T>> GetByPageAsync(int page, int pageSize, string where = null, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            int skip = 0;
            if (page > 1)
            {
                skip = (page - 1) * pageSize;
            }
            return await GetBySkipTakeAsync(skip, pageSize, where, param, returnFields, orderby, tran, timeout, cancellationToken);
        }

        public List<dynamic> GetByPageDynamic(int page, int pageSize, string where = null, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null)
        {
            int skip = 0;
            if (page > 1)
            {
                skip = (page - 1) * pageSize;
            }
            return GetBySkipTakeDynamic(skip, pageSize, where, param, returnFields, orderby, tran, timeout);
        }

        public async Task<List<dynamic>> GetByPageDynamicAsync(int page, int pageSize, string where = null, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            int skip = 0;
            if (page > 1)
            {
                skip = (page - 1) * pageSize;
            }
            return await GetBySkipTakeDynamicAsync(skip, pageSize, where, param, returnFields, orderby, tran, timeout, cancellationToken);
        }

        #endregion

        #region GetByPageAndCount

        public PageEntity<T> GetByPageAndCount(int page, int pageSize, string where = null, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return new PageEntity<T>
            {
                Data = GetByPage(page, pageSize, where, param, returnFields, orderby, tran, timeout),
                Count = Count(where, param, tran, timeout)
            };
        }

        public async Task<PageEntity<T>> GetByPageAndCountAsync(int page, int pageSize, string where = null, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            var task1 = GetByPageAsync(page, pageSize, where, param, returnFields, orderby, tran, timeout, cancellationToken);
            var task2 = CountAsync(where, param, tran, timeout, cancellationToken);
            await Task.WhenAll(task1, task2);
            return new PageEntity<T>
            {
                Data = task1.Result,
                Count = task2.Result
            };
        }

        public PageEntity<dynamic> GetByPageAndCountDynamic(int page, int pageSize, string where = null, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null)
        {
            return new PageEntity<dynamic>
            {
                Data = GetByPageDynamic(page, pageSize, where, param, returnFields, orderby, tran, timeout),
                Count = Count(where, param, tran, timeout)
            };
        }

        public async Task<PageEntity<dynamic>> GetByPageAndCountDynamicAsync(int page, int pageSize, string where = null, object param = null, string returnFields = null, string orderby = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            var task1 = GetByPageDynamicAsync(page, pageSize, where, param, returnFields, orderby, tran, timeout, cancellationToken);
            var task2 = CountAsync(where, param, tran, timeout, cancellationToken);
            await Task.WhenAll(task1, task2);
            return new PageEntity<dynamic>
            {
                Data = task1.Result,
                Count = task2.Result
            };
        }

        #endregion

        #region GetByAscDescPage

        public List<T> GetByAscDescPage(bool asc, AscDescPage adPage, int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            if (asc)
            {
                switch (adPage)
                {
                    case AscDescPage.Fist:
                        return GetByAscFirstPage(pageSize, param, and, returnFields, tran, timeout);
                    case AscDescPage.Prev:
                        return GetByAscPrevPage(pageSize, param, and, returnFields, tran, timeout);
                    case AscDescPage.Current:
                        return GetByAscCurrentPage(pageSize, param, and, returnFields, tran, timeout);
                    case AscDescPage.Next:
                        return GetByAscNextPage(pageSize, param, and, returnFields, tran, timeout);
                    case AscDescPage.Last:
                        return GetByAscLastPage(pageSize, param, and, returnFields, tran, timeout);
                }
            }
            else
            {
                switch (adPage)
                {
                    case AscDescPage.Fist:
                        return GetByDescFirstPage(pageSize, param, and, returnFields, tran, timeout);
                    case AscDescPage.Prev:
                        return GetByDescPrevPage(pageSize, param, and, returnFields, tran, timeout);
                    case AscDescPage.Current:
                        return GetByDescCurrentPage(pageSize, param, and, returnFields, tran, timeout);
                    case AscDescPage.Next:
                        return GetByDescNextPage(pageSize, param, and, returnFields, tran, timeout);
                    case AscDescPage.Last:
                        return GetByDescLastPage(pageSize, param, and, returnFields, tran, timeout);
                }
            }
            return null;
        }

        public async Task<List<T>> GetByAscDescPageAsync(bool asc, AscDescPage adPage, int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (asc)
            {
                switch (adPage)
                {
                    case AscDescPage.Fist:
                        return await GetByAscFirstPageAsync(pageSize, param, and, returnFields, tran, timeout, cancellationToken);
                    case AscDescPage.Prev:
                        return await GetByAscPrevPageAsync(pageSize, param, and, returnFields, tran, timeout, cancellationToken);
                    case AscDescPage.Current:
                        return await GetByAscCurrentPageAsync(pageSize, param, and, returnFields, tran, timeout, cancellationToken);
                    case AscDescPage.Next:
                        return await GetByAscNextPageAsync(pageSize, param, and, returnFields, tran, timeout, cancellationToken);
                    case AscDescPage.Last:
                        return await GetByAscLastPageAsync(pageSize, param, and, returnFields, tran, timeout, cancellationToken);
                }
            }
            else
            {
                switch (adPage)
                {
                    case AscDescPage.Fist:
                        return await GetByDescFirstPageAsync(pageSize, param, and, returnFields, tran, timeout, cancellationToken);
                    case AscDescPage.Prev:
                        return await GetByDescPrevPageAsync(pageSize, param, and, returnFields, tran, timeout, cancellationToken);
                    case AscDescPage.Current:
                        return await GetByDescCurrentPageAsync(pageSize, param, and, returnFields, tran, timeout, cancellationToken);
                    case AscDescPage.Next:
                        return await GetByDescNextPageAsync(pageSize, param, and, returnFields, tran, timeout, cancellationToken);
                    case AscDescPage.Last:
                        return await GetByDescLastPageAsync(pageSize, param, and, returnFields, tran, timeout, cancellationToken);
                }
            }
            return null;
        }

        public List<dynamic> GetByAscDescPageDynamic(bool asc, AscDescPage adPage, int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null)
        {
            if (asc)
            {
                switch (adPage)
                {
                    case AscDescPage.Fist:
                        return GetByAscFirstPageDynamic(pageSize, param, and, returnFields, tran, timeout);
                    case AscDescPage.Prev:
                        return GetByAscPrevPageDynamic(pageSize, param, and, returnFields, tran, timeout);
                    case AscDescPage.Current:
                        return GetByAscCurrentPageDynamic(pageSize, param, and, returnFields, tran, timeout);
                    case AscDescPage.Next:
                        return GetByAscNextPageDynamic(pageSize, param, and, returnFields, tran, timeout);
                    case AscDescPage.Last:
                        return GetByAscLastPageDynamic(pageSize, param, and, returnFields, tran, timeout);
                }
            }
            else
            {
                switch (adPage)
                {
                    case AscDescPage.Fist:
                        return GetByDescFirstPageDynamic(pageSize, param, and, returnFields, tran, timeout);
                    case AscDescPage.Prev:
                        return GetByDescPrevPageDynamic(pageSize, param, and, returnFields, tran, timeout);
                    case AscDescPage.Current:
                        return GetByDescCurrentPageDynamic(pageSize, param, and, returnFields, tran, timeout);
                    case AscDescPage.Next:
                        return GetByDescNextPageDynamic(pageSize, param, and, returnFields, tran, timeout);
                    case AscDescPage.Last:
                        return GetByDescLastPageDynamic(pageSize, param, and, returnFields, tran, timeout);
                }
            }
            return null;
        }

        public async Task<List<dynamic>> GetByAscDescPageDynamicAsync(bool asc, AscDescPage adPage, int pageSize, object param, string and = null, string returnFields = null, DistributedTransaction tran = null, int? timeout = null, CancellationToken cancellationToken = default)
        {
            if (asc)
            {
                switch (adPage)
                {
                    case AscDescPage.Fist:
                        return await GetByAscFirstPageDynamicAsync(pageSize, param, and, returnFields, tran, timeout, cancellationToken);
                    case AscDescPage.Prev:
                        return await GetByAscPrevPageDynamicAsync(pageSize, param, and, returnFields, tran, timeout, cancellationToken);
                    case AscDescPage.Current:
                        return await GetByAscCurrentPageDynamicAsync(pageSize, param, and, returnFields, tran, timeout, cancellationToken);
                    case AscDescPage.Next:
                        return await GetByAscNextPageDynamicAsync(pageSize, param, and, returnFields, tran, timeout, cancellationToken);
                    case AscDescPage.Last:
                        return await GetByAscLastPageDynamicAsync(pageSize, param, and, returnFields, tran, timeout, cancellationToken);
                }
            }
            else
            {
                switch (adPage)
                {
                    case AscDescPage.Fist:
                        return await GetByDescFirstPageDynamicAsync(pageSize, param, and, returnFields, tran, timeout, cancellationToken);
                    case AscDescPage.Prev:
                        return await GetByDescPrevPageDynamicAsync(pageSize, param, and, returnFields, tran, timeout, cancellationToken);
                    case AscDescPage.Current:
                        return await GetByDescCurrentPageDynamicAsync(pageSize, param, and, returnFields, tran, timeout, cancellationToken);
                    case AscDescPage.Next:
                        return await GetByDescNextPageDynamicAsync(pageSize, param, and, returnFields, tran, timeout, cancellationToken);
                    case AscDescPage.Last:
                        return await GetByDescLastPageDynamicAsync(pageSize, param, and, returnFields, tran, timeout, cancellationToken);
                }
            }
            return null;
        }


        #endregion

        #region Truncate

        public void Truncate()
        {
            DataBase.TruncateTable(Name);
        }

        public async Task TruncateAsync(CancellationToken cancellationToken = default)
        {
            await DataBase.TruncateTableAsync(Name, cancellationToken);
        }

        #endregion

        #region Optimize

        public void Optimize(bool final = false, bool deduplicate = false)
        {
            DataBase.OptimizeTable(Name, final, deduplicate);
        }

        public void Optimize(string partition, bool final = false, bool deduplicate = false)
        {
            DataBase.OptimizeTable(Name, partition, final, deduplicate);
        }

        #endregion

        /*******IQuery********/
        public IQuery AsQuery(bool setField = true, bool setOrderby = true)
        {
            IQuery query;
            if (DbType == DataBaseType.MySql)
            {
                query = new MySqlQuery(DataBase);
            }
            else if (DbType == DataBaseType.Postgresql)
            {
                query = new PostgreQuery(DataBase);
            }
            else if (DbType == DataBaseType.Sqlite)
            {
                query = new SQLiteQuery(DataBase);
            }
            else if (DbType == DataBaseType.Oracle)
            {
                query = new OracleQuery(DataBase);
            }
            else
            {
                query = new SqlServerQuery(DataBase);
            }
            query.Init(this, setField, setOrderby);
            return query;
        }

        public IQuery AsQueryForUpdate(bool setField = true, bool setOrderby = true)
        {
            IQuery query;
            if (DbType == DataBaseType.MySql)
            {
                query = new MySqlQuery(DataBase)
                {
                    forUpdate = " FOR UPDATE"
                };
            }
            else if (DbType == DataBaseType.Postgresql)
            {
                query = new PostgreQuery(DataBase)
                {
                    forUpdate = " FOR UPDATE"
                };
            }
            else if (DbType == DataBaseType.Sqlite)
            {
                query = new SQLiteQuery(DataBase);
            }
            else if (DbType == DataBaseType.Oracle)
            {
                query = new OracleQuery(DataBase)
                {
                    forUpdate = " FOR UPDATE"
                };
            }
            else
            {
                query = new SqlServerQuery(DataBase)
                {
                    forUpdate = " WITH(UPDLOCK)"
                };
            }
            query.Init(this, setField, setOrderby);
            return query;
        }

        public IQuery AsQueryForUpdateNoWait(bool setField = true, bool setOrderby = true)
        {
            IQuery query;
            if (DbType == DataBaseType.MySql)
            {
                query = new MySqlQuery(DataBase)
                {
                    forUpdate = " FOR UPDATE NOWAIT"
                };
            }
            else if (DbType == DataBaseType.Postgresql)
            {
                query = new PostgreQuery(DataBase)
                {
                    forUpdate = " FOR UPDATE NOWAIT"
                };
            }
            else if (DbType == DataBaseType.Sqlite)
            {
                query = new SQLiteQuery(DataBase);
            }
            else if (DbType == DataBaseType.Oracle)
            {
                query = new OracleQuery(DataBase)
                {
                    forUpdate = " FOR UPDATE NOWAIT"
                };
            }
            else
            {
                query = new SqlServerQuery(DataBase)
                {
                    forUpdate = " WITH(UPDLOCK,NOWAIT)"
                };
            }
            query.Init(this, setField, setOrderby);
            return query;
        }

        public IQuery AsQuery(string asName, bool setField = true, bool setOrderby = true)
        {
            IQuery query;
            if (DbType == DataBaseType.MySql)
            {
                query = new MySqlQuery(DataBase);
            }
            else if (DbType == DataBaseType.Postgresql)
            {
                query = new PostgreQuery(DataBase);
            }
            else if (DbType == DataBaseType.Sqlite)
            {
                query = new SQLiteQuery(DataBase);
            }
            else if (DbType == DataBaseType.Oracle)
            {
                query = new OracleQuery(DataBase);
            }
            else
            {
                query = new SqlServerQuery(DataBase);
            }
            query.Init(this, asName, setField, setOrderby);
            return query;
        }

        public IQuery AsQueryForUpdate(string asName, bool setField = true, bool setOrderby = true)
        {
            IQuery query;
            if (DbType == DataBaseType.MySql)
            {
                query = new MySqlQuery(DataBase)
                {
                    forUpdate = " FOR UPDATE"
                };
            }
            else if (DbType == DataBaseType.Postgresql)
            {
                query = new PostgreQuery(DataBase)
                {
                    forUpdate = " FOR UPDATE"
                };
            }
            else if (DbType == DataBaseType.Sqlite)
            {
                query = new SQLiteQuery(DataBase);
            }
            else if (DbType == DataBaseType.Oracle)
            {
                query = new OracleQuery(DataBase)
                {
                    forUpdate = " FOR UPDATE"
                };
            }
            else
            {
                query = new SqlServerQuery(DataBase)
                {
                    forUpdate = " WITH(UPDLOCK)"
                };
            }
            query.Init(this, asName, setField, setOrderby);
            return query;
        }

        public IQuery AsQueryForUpdateNoWait(string asName, bool setField = true, bool setOrderby = true)
        {
            IQuery query;
            if (DbType == DataBaseType.MySql)
            {
                query = new MySqlQuery(DataBase)
                {
                    forUpdate = " FOR UPDATE NOWAIT"
                };
            }
            else if (DbType == DataBaseType.Postgresql)
            {
                query = new PostgreQuery(DataBase)
                {
                    forUpdate = " FOR UPDATE NOWAIT"
                };
            }
            else if (DbType == DataBaseType.Sqlite)
            {
                query = new SQLiteQuery(DataBase);
            }
            else if (DbType == DataBaseType.Oracle)
            {
                query = new OracleQuery(DataBase)
                {
                    forUpdate = " FOR UPDATE NOWAIT"
                };
            }
            else
            {
                query = new SqlServerQuery(DataBase)
                {
                    forUpdate = " WITH(UPDLOCK,NOWAIT)"
                };
            }
            query.Init(this, asName, setField, setOrderby);
            return query;
        }
    }

}
